yahookey="[dj0yJmk9Y0RmSG1PVkx5dUNsJmQ9WVdrOVdESXliV0pWTjJVbWNHbzlNVGN4TVRBM05qTTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1jMA--]"
from xml.dom.minidom import parseString
from math import pi, sin, cos, atan2, sqrt
from urllib import urlopen,quote_plus
import sys,time

loc_cache={}

def getlocation(address):
    if address in loc_cache:
        return loc_cache[address]
    try:
        data=urlopen('http://where.yahooapis.com/geocode?q=%s&appid=%s'%(quote_plus(address),yahookey)).read( )
        doc=parseString(data)
        lat=doc.getElementsByTagName('latitude')[0].firstChild.nodeValue
        long=doc.getElementsByTagName('longitude')[0].firstChild.nodeValue
        loc_cache[address]=(float(lat),float(long))
    except IOError:
        print 'check the internet connection'
        raise
        sys.exit(-1)
    return loc_cache[address]

def haversine_distance(loc1, loc2):
    """Haversine formula - give coordinates as (lat_decimal, lon_decimal) tuples. Returns distance in miles"""
    earth_radius = 6371.0 # km 

    to_radians = lambda x : x * pi / 180.0
    lat1, lon1 = map(to_radians, loc1)
    lat2, lon2 = map(to_radians, loc2)

    # haversine formula
    hdlat = (lat2 - lat1) / 2.0
    hdlon = (lon2 - lon1) / 2.0
    a = sin(hdlat)**2 + cos(lat1) * cos(lat2) * sin(hdlon)**2
    c = 2.0 * atan2(sqrt(a), sqrt(1.0 - a))
    km = earth_radius * c
    return km * 0.621371

centerOfUSA=getlocation('Butte County,South Dakota')

cities=open('c:\Hearst\distinctCities_new.csv','r')
distCities=open('c:\Hearst\distFromCentreOfUSA_new.csv','w')

#get the distance in kms for each city from the centre of entire USA
distCenUSA={}
for ctr,city in enumerate(cities):
    city=city.rstrip('\n')
    try:
        distCenUSA[city]=round(haversine_distance(centerOfUSA,getlocation(city+',USA')),2)
    except:
       distCenUSA[city]=9999.0
    distCities.write(city+'^'+str(distCenUSA[city])+'\n')
    if ctr%100==0 and ctr!=0:
       time.sleep(8)
       print 'processed '+str(ctr)+' cities...'
       distCities.flush()
distCities.close()
    

